/*
 * @Author: “ygnnli” “1585923072@qq.com”
 * @Date: 2024-08-02 15:02:36
 * @LastEditors: “ygnnli” “1585923072@qq.com”
 * @LastEditTime: 2024-08-02 20:33:48
 * @FilePath: /110/42/Log.hpp
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#pragma once

#include <string>
#include <cstdio>
#include <iostream>
#include <time.h>
#include <sys/types.h>
#include <unistd.h>
#include <cstdarg>
#include "LockGuard.hpp"
#include <pthread.h>
#include <fstream>

const std::string logname = "log.txt"; // 保存在当前目录下
bool gIsSave = false;                  // 是否保存日志
// 日志等级
enum Level
{
    DEBUG = 0,
    INFO,
    WARNING,
    ERROR,
    FATAL
};
// 转换日志等级为字符串
std::string LevelToString(int level)
{
    switch (level)
    {
    case DEBUG:
        return "DEBUG";
    case INFO:
        return "INFO";
    case WARNING:
        return "WARNING";
    case ERROR:
        return "ERROR";
    case FATAL:
        return "FATAL";
    default:
        return "UNKNOWN";
    }
}
// 获取时间字符串
std::string GetTimeString()
{
    time_t curr_time = time(nullptr); // 阿里默认配的时区
    struct tm *format_time = localtime(&curr_time);
    if (format_time == nullptr)
    {
        return "None";
    }
    char time_buffer[1024];
    snprintf(time_buffer, sizeof(time_buffer), "%d-%d-%d %d:%d:%d",
             format_time->tm_year + 1900,
             format_time->tm_mon + 1,
             format_time->tm_mday,
             format_time->tm_hour,
             format_time->tm_min,
             format_time->tm_sec);

    return time_buffer;
}
// 1. 日志是写到文件中的
void SaveFile(const std::string &filename, const std::string &message)
{
    std::ofstream out(filename, std::ios::app);
    if (!out.is_open())
    {
        return;
    }
    out << message;
    out.close();
}

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

// 2. 日志是由格式的
// 日志等级 时间 代码所在的文件名/行数 日志的内容
void LogMessage(std::string filename, int line, bool issave, int level, const char *format, ...)
{
    std::string levelstr = LevelToString(level);
    std::string timestr = GetTimeString();
    pid_t selfid = getpid();

    char buffer[1024];
    va_list args;
    va_start(args, format);
    vsnprintf(buffer, sizeof(buffer), format, args);
    va_end(args);

    std::string message = "[" + timestr + "] [" + levelstr + "] [" + std::to_string(selfid) + "] [" + filename + "] [" + std::to_string(line) + "] [" + buffer + "]" + "\n";

    LockGuard lockguard(&lock);
    if (!issave)
    {
        std::cout << message;
    }
    else
    {
        SaveFile(logname, message);
    }
    // std::cout << levelstr << " : " << timestr << " : " << filename << " : " << line << " : " << buffer << std::endl;
    //  LogMessage(__FILE__,__LINE__ , DEBUG, "hello: %s %d, %f", "world",10 3.14);
}
// 宏：建议加 do while(0)
#define LOG(level, format, ...)                                                \
    do                                                                         \
    {                                                                          \
        LogMessage(__FILE__, __LINE__, gIsSave, level, format, ##__VA_ARGS__); \
    } while (0)
// 写入文件中
#define EnableFile()    \
    do                  \
    {                   \
        gIsSave = true; \
    } while (0)
// 写入显示器中
#define EnableScreen()   \
    do                   \
    {                    \
        gIsSave = false; \
    } while (0)